{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "(402, 3352)\n",
      "(402,)\n"
     ]
    }
   ],
   "source": [
    "#采取嵌套流水线模式\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from jqdata import *\n",
    "from jqfactor import get_factor_values\n",
    "from jqfactor import get_all_factors \n",
    "\n",
    "code='300750.XSHE'#这里以宁德时代股票为例子\n",
    "date_1='2024-01-01'#设置训练数据开始日期\n",
    "date_2='2025-08-31'#设置训练数据结束日期\n",
    "\n",
    "\n",
    "#定义滞后阶数\n",
    "lags = [1, 2, 3]\n",
    "\n",
    "#获取历史股价及计算跨日均值收益率\n",
    "df=get_price(code, start_date=date_1, end_date=date_2, frequency='daily', fields=['close','avg'], skip_paused=False, fq='pre', count=None, panel=False, fill_paused=True)\n",
    "df= df.sort_index() #确保数据df是按时间顺序排序\n",
    "y_0=df['avg']\n",
    "y = np.log(y_0.shift(-1)/y_0) # index=k，则y.iloc[k]是k到 min{t∈T_y|t>k} 日的收益率,后续可看模型效果选择对数收益率\n",
    "\n",
    "X=pd.DataFrame() #创建空dataframe用于存储调仓日前一天获取的输入特征\n",
    "\n",
    "#用调仓日前一天的股票收盘价作为特征，也可换为交易时间点的股价\n",
    "X['price_close']=df['close']\n",
    "\n",
    "#添加交易日前一天的每15min的变化率作为特征\n",
    "df = get_price(code, start_date=date_1, end_date=date_2, frequency='15m',fields=['open','close'])\n",
    "df['date'] = df.index.strftime('%Y-%m-%d')\n",
    "df['time'] = df.index.strftime('%H:%M:%S')\n",
    "df['diff_ratio'] = np.log(df['close']/df['open'])#注意这里取对数了\n",
    "df_1 = df.pivot(index='date', columns='time', values='diff_ratio')\n",
    "X=X.join(df_1, how='left')\n",
    "#添加交易日前一天的每15min的变化率作为特征\n",
    "\n",
    "#添加指数作为特征\n",
    "stock_index = get_all_securities(types=['index'], date=None)\n",
    "for i in stock_index.index:\n",
    "    df = get_price(i, start_date=date_1, end_date=date_2,frequency='daily', fields=['open', 'close', 'volume'])\n",
    "    df= df.sort_index()\n",
    "    df['ratio'] = np.log(df['close']/df['open'])\n",
    "    #同时构建df['ratio']的滞后特征\n",
    "    for lag in lags:\n",
    "        df[f'ratio_{lag}'] = df['ratio'].shift(lag)\n",
    "    df.drop(columns=['open'], axis=1, inplace=True)\n",
    "    df = df.rename(columns=lambda x: f\"{x}_{i}\")\n",
    "    X = X.join(df, how='left')\n",
    "    \n",
    "#添加资金流向作为特征\n",
    "df=get_money_flow(code, start_date=date_1, end_date=date_2, fields=None, count=None)\n",
    "df=df.set_index('date')\n",
    "df=df.drop(columns='sec_code')\n",
    "X = X.join(df, how='left')\n",
    "\n",
    "#添加基本面因子作为特征\n",
    "df = get_all_factors()\n",
    "judge = (df['category'] == 'basics')\n",
    "factors_list = df[judge]['factor'].tolist()\n",
    "factor_data = get_factor_values(securities=code, factors=factors_list, start_date=date_1, end_date=date_2)\n",
    "for key in factor_data.keys():\n",
    "    df_factor=factor_data[key].rename(columns=lambda x: f\"{x}_{key}\")\n",
    "    X = X.join(df_factor, how='left')\n",
    "\n",
    "X = X.shift(1)  \n",
    "# 执行前行标为k的行代表的是第k日获取的输入向量，执行后行为k的代表的是第 max{t∈T_X|t<k}日获取的输入向量\n",
    "\n",
    "X_tail_5=X.tail(5) #将X的最后5行存储到X_tail_5中\n",
    "columns_NotUpdate=X.columns[X_tail_5.isna().all()] #将全为na值的列的列标存储到变量columns_drop中\n",
    "X=X.drop(columns=columns_NotUpdate)\n",
    "\n",
    "#删除因构建滞后特征而出现整行确实的第一行\n",
    "X=X.iloc[1:]\n",
    "y=y.iloc[1:]\n",
    "\n",
    "print(X.index.equals(y.index))  #判断X和y的行标签是否完全一致，在批量训练的时候可以写为if判断条件\n",
    "print(X.shape)\n",
    "print(y.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "y.to_csv('y.csv',index=True)\n",
    "X.to_csv('X.csv',index=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "MarkDown菜单",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
